package controllers;

import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Collection;
import java.util.Date;
import java.util.List;

import models.Aprovacao;
import models.Eleitor;
import models.Materia;
import models.Politico;
import models.Posicao;

import org.htmlcleaner.XPatherException;

import play.modules.router.Get;
import play.mvc.Controller;
import sun.misc.BASE64Decoder;
import votenaweb.VoteNaWebParser;

import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;



public class Application extends Controller {
	private static final DateFormat FORMATADOR_DE = new SimpleDateFormat("MM/dd/yyyy");
	private static final DateFormat FORMATADOR_PARA = new SimpleDateFormat("dd/MM/yyyy");
	private static final String MALE = "male";
	
	public static void profile(Long eleitorId) {
		Eleitor eleitor = Eleitor.findById(eleitorId);
	
		Politico politicoMonitorado = eleitor.getPoliticos().iterator().next();
		List<Materia> materias = Materia.findAll();
		render(eleitor, politicoMonitorado, materias);
	}
	
    public static void index(String signed_request) {
    	BASE64Decoder decoder = new BASE64Decoder();

    	try {
    		if (signed_request != null) {
	    		int indice = signed_request.indexOf(".") + 1;
	//    		String segredo = signed_request.substring(0, indice - 1);
	    		String base64String = signed_request.substring(indice);
	    		String json = new String(decoder.decodeBuffer(base64String));
	    		json = json.substring(0, json.lastIndexOf("}") + 1);
				JsonParser parse = new JsonParser();
				JsonElement elemento = parse.parse(json);
				JsonObject objeto  = elemento.getAsJsonObject();
				JsonElement eleitorId = objeto.get("user_id");
				JsonElement oauthToken = objeto.get("oauth_token");
				if (eleitorId != null) {
					Eleitor eleitor = Eleitor.find("byFacebookID", eleitorId.getAsString()).first();
					if (eleitor != null && eleitor.isConfigurado()) {
						eleitor.setToken(oauthToken.getAsString());
						eleitor.save();
//				    	Collection<Materia> materias = VoteNaWebParser.load(politicoMonitorado);
				    	List<Materia> materias = Materia.findAll();
				        render("Application/profile.html", eleitor, materias);
					} else {
						eleitor = createUser(eleitorId.getAsString(), oauthToken.getAsString());
						List<Politico> politicos = Politico.find("from Politico p order by p.uf").fetch();
				        render("Application/setup.html", eleitor, politicos);
					}
			    } else {
		        	render("Application/redirect.html");
				}
    		}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
    
    private static Eleitor createUser(String asString, String asString2) throws IOException, ParseException {
    	StringBuffer url = new StringBuffer("https://graph.facebook.com/");
    	url.append(asString);
    	url.append("?method=GET&format=json&access_token=");
    	url.append(asString2);
    	
    	String json = getJson(url.toString());

    	JsonParser parse = new JsonParser();
		JsonElement elemento = parse.parse(json);
		JsonObject objeto  = elemento.getAsJsonObject();
    	
    	Eleitor eleitor = new Eleitor();
    	eleitor.setEmail(objeto.get("email").getAsString());
    	eleitor.setFacebookID(asString);
    	eleitor.setFoto("http://graph.facebook.com/" + asString + "/picture");
    	eleitor.setUf(objeto.getAsJsonObject("hometown").get("name").getAsString());
    	eleitor.setDataNascimento(formataData(objeto.get("birthday").getAsString()));
    	eleitor.setGenero(formataGenero(objeto.get("gender").getAsString()));
    	eleitor.setNome(objeto.get("name").getAsString());
    	eleitor.setToken(asString2);
    	
    	eleitor.save();
    	
    	return eleitor;
	}
    
    private static String formataGenero(String generoNaoFormatado) {
    	if (MALE.equalsIgnoreCase(generoNaoFormatado)) {
    		return "Masculino";
    	} else {
    		return "Feminino";
    	}
	}

	private static String formataData(String dataNaoFormatada) throws ParseException {
    	Date from = FORMATADOR_DE.parse(dataNaoFormatada);
    	return FORMATADOR_PARA.format(from);
    }
    
    private static String getJson(String uri) throws IOException {
    	URL url = new URL(uri);
    	URLConnection connection = url.openConnection();
    	InputStream input = null;
    	StringBuffer json =  new StringBuffer();
    	try {
        	input = connection.getInputStream();
        	int b = input.read();
        	while (b != -1) {
        		json.append((char) b);
        		b = input.read();
        	}
    	} finally {
    		if (input != null) {
    			input.close();
    		}
    	}
    	return json.toString();
    }
    
    @Get("/add")
    public static void add(long eleitorId, long politicoId) {
    	Eleitor eleitor = Eleitor.findById(eleitorId);
    	Politico politico = Politico.findById(politicoId);
    	
    	eleitor.getPoliticos().add(politico);
    	eleitor.setConfigurado(true);
    	eleitor.save();
    	
    	renderJSON("{\"resultado\":\"ok\"}");
    }

    @Get("/remove")
    public static void remove(long eleitorId, long politicoId) {
    	Eleitor eleitor = Eleitor.findById(eleitorId);
    	Politico politico = Politico.findById(politicoId);
    	
    	eleitor.getPoliticos().remove(politico);
    	eleitor.save();
    	
    	renderJSON("{\"resultado\":\"ok\"}");
    }

    @Get("/voto")
    public static void vote(long eleitorId, long posicaoId, int voto) {
    	Eleitor eleitor = Eleitor.findById(eleitorId);
    	Posicao posicao = Posicao.findById(posicaoId);
    	
    	Aprovacao aprovacao = new Aprovacao();
    	aprovacao.setEleitor(eleitor);
    	aprovacao.setPosicao(posicao);
    	aprovacao.setConcorda(voto == 1 ? true : false);
    	aprovacao.save();
    	
    	renderJSON("{\"success\": true, \"voto\":" + voto + ", \"posicaoId\":" + posicaoId + "}");
    }
    
    @Get("/getvotos/{politicoid}")
    public static void getvotos(String politicoid) {
    	if (politicoid != null && politicoid.length() > 0) {
    		try {
				Politico politico = Politico.find("byVoteNaWebId", politicoid).first();
				
				Collection<Materia> materias = VoteNaWebParser.load(politico);
				
				render(materias, politico.getNome());
			
			} catch (MalformedURLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (XPatherException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
    	}
    }

	public static void oauth() {
    	redirect("http://apps.facebook.com/votovivo/");
    }
}
